﻿using DiyEFConfigurationBuilder.Enums;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace DiyEFConfigurationBuilder
{
    public class EFConfigurationBuilder
    {
        /// <summary>
        /// 上下文
        /// </summary>
        private static DiyEFContext DbContext { get; set; }
        /// <summary>
        /// 配置
        /// </summary>
        public static IConfiguration EFConfiguration { get; set; }
        /// <summary>
        /// 连接字符串
        /// </summary>
        public static string ConnectionStr { get; set; }

        /// <summary>
        /// 创建配置
        /// </summary>
        /// <param name="diyConfig"></param>
        /// <returns></returns>
        public static (bool, string) CreateConfig(DiyConfig diyConfig)
        {
            if (DbContext == null)
            {
                return (false, "未初始化上下文，请检查！");
            }
            if (diyConfig == null && DbContext.DiyConfigs.Any(x => x.Id.Equals(diyConfig.Id)))
            {
                return (false, "传入参数有误，请检查！");
            }
            if (DbContext.DiyConfigs.Any(x => x.Key.Equals(diyConfig.Key)))
            {
                return (false, "DB—已有对应的键值对");
            }
            DbContext.DiyConfigs.Add(diyConfig);
            if (DbContext.SaveChanges() > 0)
            {
                return (true, "成功");
            }
            else
            {
                return (false, "创建配置失败");
            }
        }

        /// <summary>
        /// 创建配置
        /// </summary>
        /// <param name="diyConfig"></param>
        /// <returns></returns>
        public static async Task<(bool, string)> CreateConfigAsync(DiyConfig diyConfig)
        {
            if (DbContext == null)
            {
                return (false, "未初始化上下文，请检查！");
            }
            if (diyConfig == null && DbContext.DiyConfigs.Any(x => x.Id.Equals(diyConfig.Id)))
            {
                return (false, "传入参数有误，请检查！");
            }
            DbContext.DiyConfigs.Add(diyConfig);
            if (await DbContext.SaveChangesAsync() > 0)
            {
                return (true, "成功");
            }
            else
            {
                return (false, "创建配置失败");
            }
        }


        /// <summary>
        /// 删除配置
        /// </summary>
        /// <param name="diyConfig"></param>
        /// <returns></returns>
        public static async Task<(bool, string)> DleteConfigAsync(DiyConfig diyConfig)
        {
            if (DbContext == null)
            {
                return (false, "未初始化上下文，请检查！");
            }
            if (diyConfig == null && !DbContext.DiyConfigs.Any(x => x.Id.Equals(diyConfig.Id)))
            {
                return (false, "传入参数有误，请检查！");
            }
            DbContext.DiyConfigs.Remove(diyConfig);
            if (await DbContext.SaveChangesAsync() > 0)
            {
                return (true, "成功");
            }
            else
            {
                return (false, "更新配置失败");
            }
        }

        /// <summary>
        /// 删除配置
        /// </summary>
        /// <param name="diyConfig"></param>
        /// <returns></returns>
        public static (bool, string) DleteConfig(DiyConfig diyConfig)
        {
            try
            {
                if (DbContext == null)
                {
                    return (false, "未初始化上下文，请检查！");
                }
                if (diyConfig == null && !DbContext.DiyConfigs.Any(x => x.Id.Equals(diyConfig.Id)))
                {
                    return (false, "传入参数有误，请检查！");
                }
                DbContext.DiyConfigs.Remove(diyConfig);
                if (DbContext.SaveChanges() > 0)
                {
                    return (true, "成功");
                }
                else
                {
                    return (false, "更新配置失败");
                }
            }
            catch (Exception ex)
            {
                return (false, $"更新配置失败,error:{ex.Message}");
            }
        }

        /// <summary>
        /// 更新配置
        /// </summary>
        /// <param name="diyConfig"></param>
        /// <returns></returns>
        public (bool, string) UpdateConfig(DiyConfig diyConfig)
        {
            try
            {
                if (DbContext == null)
                {
                    return (false, "未初始化上下文，请检查！");
                }
                if (diyConfig == null && !DbContext.DiyConfigs.Any(x => x.Id.Equals(diyConfig.Id)))
                {
                    return (false, "传入参数有误，请检查！");
                }
                DbContext.DiyConfigs.Update(diyConfig);
                if (DbContext.SaveChanges() > 0)
                {
                    return (true, "成功");
                }
                else
                {
                    return (false, "更新配置失败");
                }
            }
            catch (Exception ex)
            {
                return (false, $"更新配置失败,error:{ex.Message}");
            }
        }

        /// <summary>
        /// 更新配置
        /// </summary>
        /// <param name="diyConfig"></param>
        /// <returns></returns>
        public async Task<(bool, string)> UpdateConfigAsync(DiyConfig diyConfig)
        {
            try
            {
                if (DbContext == null)
                {
                    return (false, "未初始化上下文，请检查！");
                }
                if (diyConfig == null && !await DbContext.DiyConfigs.AnyAsync(x => x.Id.Equals(diyConfig.Id)))
                {
                    return (false, "传入参数有误，请检查！");
                }
                DbContext.DiyConfigs.Update(diyConfig);
                if (await DbContext.SaveChangesAsync() > 0)
                {
                    return (true, "成功");
                }
                else
                {
                    return (false, "更新配置失败");
                }
            }
            catch (Exception ex)
            {
                return (false, $"更新配置失败,error:{ex.Message}");
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="connetcion">连接字符串</param>
        /// <param name="dbType">数据库类型</param>
        /// <param name="erroMesg">错误消息</param>
        /// <param name="version">数据库版本</param>
        /// <returns>IConfiguration</returns>
        public static IConfiguration Init(string connetcion, DbType dbType, out string erroMesg, string version = "5.7.28-mysql")
        {
            try
            {
                erroMesg = string.Empty;
                ServerVersion serverVersion = ServerVersion.Parse(version);
                ConnectionStr = connetcion;
                if (string.IsNullOrEmpty(connetcion) && !Enum.IsDefined(typeof(DbType), dbType))
                {
                    erroMesg = "请检查连接字符串以及数据库类型";
                    return null;
                }
                var contextOptions = new DbContextOptions<DiyEFContext>();

                if (dbType.Equals(DbType.SqLite))
                {
                    contextOptions = new DbContextOptionsBuilder<DiyEFContext>()
                         .UseSqlite(connetcion)
                         .Options;
                }
                if (dbType.Equals(DbType.SqlServer))
                {
                    contextOptions = new DbContextOptionsBuilder<DiyEFContext>()
                         .UseSqlServer(connetcion)
                         .Options;
                }
                if (dbType.Equals(DbType.MySql))
                {
                    contextOptions = new DbContextOptionsBuilder<DiyEFContext>()
                         .UseMySql(connetcion, serverVersion)
                         .Options;
                }
                DbContext = new DiyEFContext(contextOptions);
                CreateEFConfiguration();
                return EFConfiguration;
            }
            catch (Exception ex)
            {
                erroMesg = ex.Message;
                return null;
            }
        }

        /// <summary>
        /// 创建一个新的IConfiguration
        /// </summary>
        /// <returns>IConfiguration</returns>
        public static IConfiguration CreateEFConfiguration()
        {
            var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appsettings.json");
            if (!File.Exists(filePath))
            {
                EFConfiguration = new ConfigurationBuilder()
                    .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
                    .Add(new EFConfigurationSource { ReloadDelay = 500, ReloadOnChange = true, DBContext = DbContext })
                    .Build();
            }
            else
            {
                EFConfiguration = new ConfigurationBuilder()
                   .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
                   .Add(new EFConfigurationSource { ReloadDelay = 500, ReloadOnChange = true, DBContext = DbContext })
                   .Add(new JsonConfigurationSource { Path = "appsettings.json", ReloadOnChange = true })
                   .Build();
            }
            return EFConfiguration;
        }
    }
}
